package com.math.aistudykbr.utils;

import com.math.aistudykbr.pojo.entity.DocumentChunk;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 智能文本分块工具类
 */
@Component
@Slf4j
public class IntelligentTextSplitter  {

    // 语义分界正则表达式（预编译提升性能）
    private static final Pattern HEADING_PATTERN = Pattern.compile("^(#{1,6}\\s|</h[1-6]>|#+)");
    private static final Pattern SENTENCE_BREAKS = Pattern.compile("([。！？]|\\.\\s+|\\n{2,}|\\r\\n\\r\\n)");

    /**
     * 带重叠的分块方法（适用于保持语义连贯的场景）
     * @param text 原始文本内容
     * @param chunkSize 单个分块的最大长度
     * @param overlap 分块之间的重叠长度
     * @return 包含重叠的分块列表（自动去除空块）
     */
    public static List<DocumentChunk> splitWithOverlap(String text, int chunkSize, int overlap) {
        // 参数校验
        if (chunkSize <= 0) throw new IllegalArgumentException("分块尺寸必须大于0");
        if (overlap < 0 || overlap >= chunkSize) throw new IllegalArgumentException("重叠量需满足 0 ≤ overlap < chunkSize");

        List<DocumentChunk> chunks = new ArrayList<>();
        int length = text.length();
        int start = 0;

        while (start < length) {
            // 计算当前块的理论结束位置
            int end = Math.min(start + chunkSize, length);

            // 智能断点检测（从end-overlap开始查找）
            int searchStart = Math.max(start, end - overlap);
            int actualEnd = findBreakPoint(text, searchStart, end);

            // 处理未找到合适断点的情况
            if (actualEnd == -1 || actualEnd <= start) {
                actualEnd = Math.min(start + chunkSize, length);
            } else {
                actualEnd = Math.min(actualEnd, length);
            }

            // 生成有效分块
            if (start < actualEnd) {
                String chunkText = text.substring(start, actualEnd).trim();
                if (!chunkText.isEmpty()) {
                    chunks.add(new DocumentChunk(chunkText));
                }
            }

            // 更新起始位置（带重叠控制）
            int nextStart = actualEnd - overlap;
            start = (nextStart > start) ? nextStart : actualEnd; // 确保至少前进1个字符

            // 剩余文本不足时的终止条件
            if (start + chunkSize - overlap > length) break;
        }

        return chunks;
    }

    /**
     * 智能断点检测（按优先级寻找最佳分割位置）
     * 查找顺序：段落分隔 > 标题起始 > 句子结尾
     * @param text 目标文本
     * @param start 推荐起始查找位置（包含）
     * @param end 查找结束位置（不包含）
     * @return 最佳分割位置索引，找不到返回-1
     */
    private static int findBreakPoint(String text, int start, int end) {
        // 1. 段落分隔检测（支持多种换行格式）
        int paragraphBreak = findLastMatch(text, start, end, "\n\n", "\r\n\r\n");
        if (paragraphBreak != -1) return paragraphBreak;

        // 2. 标题结构检测（Markdown/HTML）
        Matcher headingMatcher = HEADING_PATTERN.matcher(text.substring(start, end));
        if (headingMatcher.find()) {
            return start + headingMatcher.start();
        }

        // 3. 句子结束检测（支持中英文标点）
        Matcher sentenceMatcher = SENTENCE_BREAKS.matcher(text.substring(start, end));
        int lastSentenceEnd = -1;
        while (sentenceMatcher.find()) {
            lastSentenceEnd = start + sentenceMatcher.end();
        }
        if (lastSentenceEnd != -1) return lastSentenceEnd;

        // 4. 找不到语义断点时返回-1
        return -1;
    }

    /**
     * 通用分隔符查找（支持多个候选模式）
     */
    private static int findLastMatch(String text, int start, int end, String... patterns) {
        for (String pattern : patterns) {
            int index = text.lastIndexOf(pattern, end);
            if (index >= start) return index + pattern.length();
        }
        return -1;
    }
}